package com.backwaveweibo.bww.controller;

import com.backwaveweibo.bww.entity.Weibo;
import com.backwaveweibo.bww.service.ElasticsearchService;
import com.backwaveweibo.bww.service.LikeService;
import com.backwaveweibo.bww.service.WeiboService;
import com.backwaveweibo.bww.utils.FileUploadWithQiNiuYun;
import com.backwaveweibo.bww.utils.Result;
import com.backwaveweibo.bww.utils.ResultCode;
import com.backwaveweibo.bww.utils.ResultGenerator;
import com.jn.sqlhelper.dialect.pagination.PagingRequest;
import com.jn.sqlhelper.dialect.pagination.PagingRequestContextHolder;
import com.jn.sqlhelper.dialect.pagination.SqlPaginations;
import com.qiniu.common.QiniuException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.elasticsearch.search.SearchHit;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author GHW : RD-Kelsey
 * @description 微博 - 表述层
 * @date 2020/6/9
 */

@RestController
@RequestMapping("weibo")
@Slf4j
public class WeiboController {
    @Resource
    private ElasticsearchService<Weibo> elasticsearchService;
    @Resource
    private WeiboService weiboService;
    @Resource
    private LikeService likeService;

    /**
     * 发表微博，并且数据会同步到 Elasticsearch
     * 需要权限: 用户 | 管理员
     *
     * @param weibo weibo.content 不可为空，
     *              weibo.userfile 可以为空，如果有，必须传入文件的外链，
     *              外链在{@link WeiboController#fileUpload(org.springframework.web.multipart.MultipartFile[])}返回
     * @return 成功返回数据, 失败返回false
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @PostMapping("add")
    public Result addWeibo(@RequestBody Weibo weibo) throws IOException {
        boolean result = weiboService.addWeibo(weibo);
        if (result) {
            //查询出刚刚插入的微博
            Weibo data = weiboService.queryById(weibo.getWeiboId());
            //增量同步微博到ES
            boolean importToES = elasticsearchService.importToES(String.valueOf(weibo.getWeiboId()), data, "weibo");
            //返回信息
            List<Weibo> toResponse = weiboService.getWeiboInfoByCondition(null);
            if (importToES) {
                return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "微博发布成功==ES同步状态==>true", toResponse);
            }
            return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "微博发布成功==ES同步状态==>false", toResponse);
        }
        return ResultGenerator.genFailResult(ResultCode.FAIL, "数据库错误==>数据存储失败", false);
    }

    /**
     * 文件上传，
     * 需要权限: 用户 | 管理员
     * 需要：Content-Type必须是multipart/form-data
     *
     * @param weiboFile multipart/form-data 文件流，可以是多个
     * @return 返回上传成功的文件外链，失败则返回false
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @PostMapping("fileUpload")
    public Result fileUpload(MultipartFile[] weiboFile) throws IOException {
        List<String> linkList = new ArrayList<>();
        String resultLink;
        for (MultipartFile file : weiboFile) {
            if (file.getOriginalFilename() == null || file.getOriginalFilename().equals("")) {
                return ResultGenerator.genFailResult(ResultCode.FAIL, "未上传文件", false);
            }
            //获取每张图片的输入流
            //获取每张图片的名字交给工具类加工
            //上传到七牛云，取得返回的链接
            resultLink = FileUploadWithQiNiuYun.uploadQNImg(file.getInputStream(), file.getOriginalFilename());
            //加入到集合用于返回链接集合
            linkList.add(resultLink);
        }
        return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "图片上传成功！", linkList);
    }

    /**
     * 按条件获取微博信息，进行分页，可传入实体中的任意允许的参数，无参数则全查
     *
     * @param weibo 实体，可以为空
     *              允许的参数：
     *              weiboId : 微博的id，查询对应id的微博
     *              forward : 转发的微博id，如果这是一条转发的微博，必传
     *              content : 微博的内容，按照微博的内容模糊查询
     *              date : 按照发布的微博的日期模糊查询
     * @return 如果参数为空返回全部微博信息，如果有参数则拼接条件返回对应条件的信息，如果微博转发了某条微博
     * 则把被转发的微博也一起返回
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("getWeiboByCondition")
    public Result getWeiboInfoByCondition(Weibo weibo) {
        //分页--默认第一页和全部数据
        PagingRequest<Weibo, Weibo> request = SqlPaginations.preparePagination(1, -1);
        PagingRequestContextHolder.getContext().setPagingRequest(request);
        List<Weibo> weiboList = weiboService.getWeiboInfoByCondition(weibo);
        //被转发的微博
        List<Weibo> infoByForward = new ArrayList<>();
        for (Weibo w : weiboList) {
            //把该条微博的点赞数返回
            w.setLikeCount(likeService.getLikeCount(w.getWeiboId()));
            //如果该条微博转发了一条微博，把被转发的那条微博带上一起返回
            if (w.getForward() != null) {
                infoByForward.add(weiboService.queryById(w.getForward()));
            }
        }
        return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "查询微博成功", request.getResult().setItems(weiboList), infoByForward);
    }

    /**
     * 返回全部用户的微博 以及 当前登录用户的微博总条数
     *
     * @return 成功返回数据，失败返回false
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("getAll")
    public Result getAllWeibo() {
        //获取<所有用户>的微博
        List<Weibo> weiboList = weiboService.queryAll();
        //获取<当前用户>微博的总条数
        PagingRequest<Weibo, Weibo> current = SqlPaginations.preparePagination(1, -1);
        PagingRequestContextHolder.getContext().setPagingRequest(current);
        List<Weibo> count = weiboService.countCurrentUserWeibo();
        if (current != null) {
            return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "查询成功", weiboList, current.getResult().setItems(count));
        } else {
            return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "查询成功", weiboList);
        }
    }

    /**
     * 删除微博，必须传入weiboId
     * 需要权限: 用户 | 管理员
     *
     * @param weiboId 微博id
     * @return 成功返回true，失败返回false
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("delete")
    public Result deleteWeibo(@RequestParam("weiboId") Long weiboId) throws QiniuException {
        boolean result = weiboService.deleteWeibo(weiboId);
        if (result) {
            boolean deleteFromES = elasticsearchService.deleteFromES("weibo", String.valueOf(weiboId));
            if (deleteFromES) {
                return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "微博删除成功==ES同步状态==true", true);
            }
            return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "微博删除成功==ES同步状态==false", true);
        }
        return ResultGenerator.genFailResult(ResultCode.FAIL, "数据库错误", false);
    }

    /**
     * 使用ES进行搜索
     *
     * @param content 内容
     * @return Map
     * @throws IOException 1
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("search")
    public Result search(@RequestParam String content) throws IOException {
        SearchHit[] result = elasticsearchService.getByContent(content);
        return ResultGenerator.genSuccessResult(ResultCode.SUCCESS, "成功", CollectionUtils.arrayToList(result));
    }
}
